package com.markhsiu.common.memory;

/**
 * 大部分用户的操作系统（如windows, FreeBsd,Linux）是Little Endian的。
 *  少部分，如MAC OS ,是Big Endian 的。
 *  
 *  字节转换，当前值支持Little Endian
 * @author Mark Hsiu
 *
 */
class Bits {  
	

    private Bits() { }

    // -- get/put char --

    static private char makeChar(byte b1, byte b0) {
        return (char)((b1 << 8) | (b0 & 0xff));
    }

    static char toChar(byte b0, byte b1) {
        return makeChar(b1, b0);
    }
    
    static char getChar(ByteBuff bb, int b0,int b1) {
        return makeChar(bb._get(b1),
                        bb._get(b0));
    }



    private static byte char1(char x) { return (byte)(x >> 8); }
    private static byte char0(char x) { return (byte)(x     ); }

    static void putChar(ByteBuff bb, int b0, int b1, char x) {
        bb._put(b0, char1(x));
        bb._put(b1, char0(x));
    }


    // -- get/put short --

    static private short makeShort(byte b1, byte b0) {
        return (short)((b1 << 8) | (b0 & 0xff));
    }

    static short toShort(byte b0, byte b1) {
        return makeShort(b1, b0);
    }
    
    static short getShort(ByteBuff bb, int b0, int b1) {
        return makeShort(bb._get(b1),
                         bb._get(b0));
    }


    private static byte short1(short x) { return (byte)(x >> 8); }
    private static byte short0(short x) { return (byte)(x     ); }



    static void putShort(ByteBuff bb, int b0, int b1, short x) {
        bb._put(b0, short1(x));
        bb._put(b1, short0(x));
    }

    // -- get/put int --
    
    static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
        return (((b3       ) << 24) |
                ((b2 & 0xff) << 16) |
                ((b1 & 0xff) <<  8) |
                ((b0 & 0xff)      ));
    }

    static int toInt(byte b0, byte b1, byte b2, byte b3) {
    	return makeInt(b3, b2, b1, b0);
    }
    
    static int getInt(ByteBuff bb, int b0, int b1,int b2, int b3) {
        return makeInt(bb._get(b3),
                       bb._get(b2),
                       bb._get(b1),
                       bb._get(b0));
    }


    private static byte int3(int x) { return (byte)(x >> 24); }
    private static byte int2(int x) { return (byte)(x >> 16); }
    private static byte int1(int x) { return (byte)(x >>  8); }
    private static byte int0(int x) { return (byte)(x      ); }


    static void putInt(ByteBuff bb, int b0, int b1,int b2, int b3, int x) {
        bb._put(b0, int0(x));
        bb._put(b1, int1(x));
        bb._put(b2, int2(x));
        bb._put(b3, int3(x));
    }


    // -- get/put long --

    static private long makeLong(byte b7, byte b6, byte b5, byte b4,
                                 byte b3, byte b2, byte b1, byte b0)
    {
        return ((((long)b7       ) << 56) |
                (((long)b6 & 0xff) << 48) |
                (((long)b5 & 0xff) << 40) |
                (((long)b4 & 0xff) << 32) |
                (((long)b3 & 0xff) << 24) |
                (((long)b2 & 0xff) << 16) |
                (((long)b1 & 0xff) <<  8) |
                (((long)b0 & 0xff)      ));
    }

 

    static long getLong(ByteBuff bb, int b0, int b1, int b2, int b3,
    		 					     int b4, int b5, int b6, int b7) {
        return makeLong(bb._get(b7),
                        bb._get(b6),
                        bb._get(b5),
                        bb._get(b4),
                        bb._get(b3),
                        bb._get(b2),
                        bb._get(b1),
                        bb._get(b0));
    }

  

    private static byte long7(long x) { return (byte)(x >> 56); }
    private static byte long6(long x) { return (byte)(x >> 48); }
    private static byte long5(long x) { return (byte)(x >> 40); }
    private static byte long4(long x) { return (byte)(x >> 32); }
    private static byte long3(long x) { return (byte)(x >> 24); }
    private static byte long2(long x) { return (byte)(x >> 16); }
    private static byte long1(long x) { return (byte)(x >>  8); }
    private static byte long0(long x) { return (byte)(x      ); }


   
    static void putLong(ByteBuff bb, int b0, int b1, int b2, int b3,
		     						 int b4, int b5, int b6, int b7, long x) {
        bb._put(b0, long0(x));
        bb._put(b1, long1(x));
        bb._put(b2, long2(x));
        bb._put(b3, long3(x));
        bb._put(b4, long4(x));
        bb._put(b5, long5(x));
        bb._put(b6, long6(x));
        bb._put(b7, long7(x));
    }

   


    // -- get/put float --


    static float getFloat(ByteBuff bb, int b0, int b1, int b2, int b3) {
        return Float.intBitsToFloat(getInt(bb, b3, b2, b1, b0));
    }


    static void putFloat(ByteBuff bb, int b0, int b1, int b2, int b3, float x) {
        putInt(bb, b3, b2, b1, b0, Float.floatToRawIntBits(x));
    }


    // -- get/put Double --

    static double getDouble(ByteBuff bb, int b0, int b1, int b2, int b3,
		     							 int b4, int b5, int b6, int b7 ) {
        return Double.longBitsToDouble(getLong(bb, b7, b6, b5, b4, b3, b2, b1, b0));
    }

    static void putDouble(ByteBuff bb, int b0, int b1, int b2, int b3,
		     						   int b4, int b5, int b6, int b7, double x) {
        putLong(bb, b7, b6, b5, b4, b3, b2, b1, b0, Double.doubleToRawLongBits(x));
    }

 
   
}
